package com.example.zqq.fivechess.five_ai;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

import com.example.zqq.fivechess.GameCallBack;
import com.example.zqq.fivechess.R;

/**
 * 五子棋 AI  View on 2017/11/10.
 */

public class FiveAIChessView extends View  implements View.OnTouchListener{

    //一些常量
    public static final int NO_CHESS = 0;           //无子----【增加】
    public static final int WHITE_CHESS = 1;         //白棋
    public static final int BLACK_CHESS = 2;         //黑棋
    public static final int WHITE_WIN = 101;         //白棋赢
    public static final int BLACK_WIN = 102;         //黑棋赢
    public static final int NO_WIN = 103;            //平局

    private Paint paint;
    private int[][] chessArray;          //棋子数组：0->无子，1->白棋，2->黑棋
    private boolean isWhite = true;      //当前下棋顺序(默认白棋先下)
    private boolean isGameOver = false;  //游戏是否结束

    //bitmap
    private Bitmap whiteChess;
    private Bitmap blackChess;

    //Rect
    private Rect rect;
    private float len;              //棋盘宽高
    private int GridNumber = 15;    //棋盘格数
    private float preWidth;          //每格之间的距离
    private float offset;            //边距

    private GameCallBack callBack;               //游戏回调
    private int whiteChessCount, blackChessCount;//当前黑白棋胜利次数

    private boolean isUserBout = true;      //是否是玩家的回合----【增加】
    private int userChess = WHITE_CHESS;    //玩家执子颜色----【增加】

    private int userScore = 0, aiScore = 0; //玩家/AI胜利次数----【增加】


    public FiveAIChessView(Context context) {
        this(context, null);
    }

    public FiveAIChessView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FiveAIChessView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    //初始化
    private void init(Context context) {
        paint = new Paint();
        paint.setAntiAlias(true);//设置抗锯齿
        paint.setColor(Color.BLACK);

        //初始化chessArray
        chessArray = new int[GridNumber][GridNumber];

        //初始化棋子图片bitmap
        whiteChess = BitmapFactory.decodeResource(getResources(), R.mipmap.stone_w2);
        blackChess = BitmapFactory.decodeResource(getResources(), R.mipmap.stone_b1);

        //初始化胜利局数
        whiteChessCount = 0;
        blackChessCount = 0;

        //初始化Rect
        rect = new Rect();

        //设置点击监听
        setOnTouchListener(this);

        //重置棋盘状态
        for (int i = 0; i < GridNumber; i++) {
            for (int j = 0; j < GridNumber; j++) {
                chessArray[i][j] = 0;
            }
        }
    }

    /**
     * 重新测量宽高，确保宽高一样
     *
     * @param widthMeasureSpec  屏幕宽
     * @param heightMeasureSpec 屏幕高
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //获取高宽值
        int width = MeasureSpec.getSize(widthMeasureSpec);      //720
        int height = MeasureSpec.getSize(heightMeasureSpec);    //1158

        //获取宽高中较小的值
        int len = width > height ? height : width;              //720

        //重新设置宽高
        setMeasuredDimension(len, len);//len--此处值传给onDraw()方法的getWidth()与getHeight()
    }

    /**
     * 5. 棋盘的绘制工作 （触摸执行）
     * 如果继承自View（初始执行）
     * 如果继承自SurfaceView（需要自己定制）
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.e("Tag--5", "onDraw");
        //棋盘为一个GRID_NUMBER * GRID_NUMBER的正方形，所有棋盘宽高必须一样
        //此处getWidth 与 getHeight 来自onMeasure（）方法
        len = getWidth() > getHeight() ? getHeight() : getWidth();//（视图view宽高）棋盘宽高
        preWidth = len / GridNumber;            //格子间距=720/15=48
        offset = preWidth / 2;                  //边距=48/2=24

        //棋盘线条，起点【24,24】
        for (int i = 0; i < GridNumber; i++) {
            float start = i * preWidth + offset;

            canvas.drawLine(offset, start, len - offset, start, paint);//画横线，x轴起点与终点不变，y轴按格子宽度变化
            canvas.drawLine(start, offset, start, len - offset, paint);//画竖线，x循环增加，y不变
        }

        //绘制棋子
        for (int i = 0; i < GridNumber; i++) {
            for (int j = 0; j < GridNumber; j++) {
                //rect中心坐标
                float rectX = offset + i * preWidth;    //相当于每次移动的距离
                float rectY = offset + j * preWidth;

                //设置rect位置(绘制矩形的位置--从【0,0】坐标开始)
                rect.set((int) (rectX - offset), (int) (rectY - offset),
                        (int) (rectX + offset), (int) (rectY + offset));

                //遍历chessArray
                switch (chessArray[i][j]) {
                    case WHITE_CHESS:       //绘制白棋
                        canvas.drawBitmap(whiteChess, null, rect, paint);
                        break;
                    case BLACK_CHESS:
                        canvas.drawBitmap(blackChess, null, rect, paint);
                        break;
                }
            }
        }
    }

    /**
     * 4. 处理我们下棋子的位置：（触摸执行）
     */
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.e("Tag--4", "onTouchEvent");
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //玩家的回合
                if (!isGameOver && isUserBout) {    //----【增加】
                    //获取按下时的位置
                    float downX = event.getX();
                    float downY = event.getY();

                    //点击的位置在棋盘上
                    if (downX >= offset / 2 && downX < len - offset / 2 &&
                            downY >= offset / 2 && downY < len - offset / 2) {
                        //获取棋子对应的位置
                        int x = (int) (downX / preWidth);//点击的位置只取 preWidth的倍数（即0、1、...14）
                        int y = (int) (downY / preWidth);

                        //判断当前位置是否已经有子
                        if (chessArray[x][y] != WHITE_CHESS && chessArray[x][y] != BLACK_CHESS) {
                            //给数组赋值
                            chessArray[x][y] = userChess;   //----【修改】

                            //修改当前落子颜色
                            isWhite = userChess == WHITE_CHESS; //----【修改】

                            //修改当前为电脑执子
                            isUserBout = false;         //----【增加】

                            //更新棋盘
                            postInvalidate();

                            //判断是否结束
                            checkGameOver();

                            //回调当前执子
                            if (callBack != null) {
                                callBack.ChangeGamer(isWhite);
                            }
                        }
                    }
                } else {
                    Toast.makeText(getContext(), "游戏已经结束，请重新开始！", Toast.LENGTH_SHORT).show();
                }
                break;
        }
        return false;
    }

    /**
     * 判断是否结束
     */
    private void checkGameOver() {
        //获取落子的颜色（如果当前是白色，则落子是黑子）
        int chess = isWhite ? BLACK_CHESS : WHITE_CHESS;

        //棋盘是否填满
        boolean isFull = true;

        //遍历chessArray
        for (int i = 0; i < GridNumber; i++) {
            for (int j = 0; j < GridNumber; j++) {
                //判断棋盘是否填满
                if (chessArray[i][j] != BLACK_CHESS && chessArray[i][j] != WHITE_CHESS) {
                    isFull = false;
                }

                //只需判断落子是否五连即可--chess只能是1/2
                if (chessArray[i][j] == chess) {

                    //判断五子相连
                    if (isFiveSame(i, j)) {
                        //五子相连游戏结束
                        isGameOver = true;

                        if (callBack != null) {
                            //判断黑白棋胜利
                            if (chess == WHITE_CHESS) {
                                whiteChessCount++;
                            } else {
                                blackChessCount++;
                            }

                            //判断玩家/AI 胜利 ----【增加】
                            if (userChess == chess) {
                                userScore++;
                            } else {
                                aiScore++;
                            }

                            callBack.GameOver(chess == WHITE_CHESS ? WHITE_WIN : BLACK_WIN);
                        }
                        return;
                    }
                }
            }
        }

        //如果棋盘填满，平局，结束
        if (isFull) {
            isGameOver = true;
            if (callBack != null) {
                callBack.GameOver(NO_WIN);
            }
        }
    }

    /**
     * 判断是否五子相连
     */
    private boolean isFiveSame(int x, int y) {
        //横向判断
        if (x + 4 < GridNumber) {
            if (chessArray[x][y] == chessArray[x + 1][y] &&
                    chessArray[x][y] == chessArray[x + 2][y] &&
                    chessArray[x][y] == chessArray[x + 3][y] &&
                    chessArray[x][y] == chessArray[x + 4][y]) {
                return true;
            }
        }

        //纵向判断
        if (y + 4 < GridNumber) {
            if (chessArray[x][y] == chessArray[x][y + 1] &&
                    chessArray[x][y] == chessArray[x][y + 2] &&
                    chessArray[x][y] == chessArray[x][y + 3] &&
                    chessArray[x][y] == chessArray[x][y + 4]) {
                return true;
            }
        }

        //判断斜向(左上到右下)
        if (y + 4 < GridNumber && x + 4 < GridNumber) {
            if (chessArray[x][y] == chessArray[x + 1][y + 1] &&
                    chessArray[x][y] == chessArray[x + 2][y + 2] &&
                    chessArray[x][y] == chessArray[x + 3][y + 3] &&
                    chessArray[x][y] == chessArray[x + 4][y + 4]) {
                return true;
            }
        }

        //判断斜向(左下到右上)
        if (y - 4 > 0 && x + 4 < GridNumber) {
            if (chessArray[x][y] == chessArray[x + 1][y - 1] &&
                    chessArray[x][y] == chessArray[x + 2][y - 2] &&
                    chessArray[x][y] == chessArray[x + 3][y - 3] &&
                    chessArray[x][y] == chessArray[x + 4][y - 4]) {
                return true;
            }
        }
        return false;
    }

    /**
     * 重置游戏
     */
    public void resetGame() {
        isGameOver = false;
        //重置棋盘状态
        for (int i = 0; i < GridNumber; i++) {
            for (int j = 0; j < GridNumber; j++) {
                chessArray[i][j] = 0;
            }
        }
        //更新UI
        postInvalidate();
    }

    //电脑判断游戏结束 ----【增加】
    public void checkAiGameOver() {
        isWhite = userChess == WHITE_CHESS;     //if语句
        checkGameOver();
    }


    public void setCallBack(GameCallBack callBack) {
        this.callBack = callBack;
    }

    public int getWhiteChessCount() {
        return whiteChessCount;
    }

    public int getBlackChessCount() {
        return blackChessCount;
    }


    //----【增加】
    public int[][] getChessArray() {
        return chessArray;
    }

    public void setUserBout(boolean userBout) {
        isUserBout = userBout;
    }

    public void setUserChess(int userChess) {
        this.userChess = userChess;
    }

    public int getUserScore() {
        return userScore;
    }

    public int getAiScore() {
        return aiScore;
    }
}
